-- DungeonMineM
-- Created by chengb Mar/10/2015
-- 地牢矿脉

module("DungeonMineM", package.seeall);

-- 矿脉配置表
local mineTable = {};

-- 矿脉列表
local mineList = {};

-- 内部函数声明
local clearMineBonus;
local takeMineBonus;
local whenHeroDie;
local whenNextFloor;
local whenLeaveDungeon;

-- 载入配置表
local _init = false;
local loadCsv = function()
    if _init then return end
    _init = true;

    local dungeon_mine_CSV = get_dungeon_mine_CSV();
    for i = 1, #dungeon_mine_CSV do
        local id = dungeon_mine_CSV[i].id;
        mineTable[id] = dungeon_mine_CSV[i];
    end
    dungeon_mine_CSV = nil;

    mineList = table.values(mineTable);

    -- 按照id升序，为了和服务器随机时一致
    table.sort(mineList, function(a, b) return a.id < b.id; end);
end

-- 初始化
function init()
    loadCsv();

    -- 关注玩家死亡的事件
    EventMgr.removeAll("DungeonMineM");
    EventMgr.register("DungeonMineM", event.HERO_DIE, function()
        whenHeroDie();
    end);

    -- 关注进入下一层的事件
    EventMgr.register("DungeonMineM", event.NEXT_FLOOR, function()
        whenNextFloor();
    end);

    -- 关注玩家离开地牢的事件
    EventMgr.register("DungeonMineM", event.LEAVE_DUNGEON, function()
        whenLeaveDungeon();
    end);
end

-- 检索配置
function query(id, path)
    local m = mineTable[id];

    if not m or path == "" or not path then
        return m;
    end

    return m[path];
end

-- 玩家死亡的回调
function whenHeroDie()
    -- 如果有矿脉奖励
    if haveMineBonus()then
        -- 直接清除
        clearMineBonus();
    end
end

-- 进入下一层的回调
function whenNextFloor()
    -- 没有矿脉奖励，不处理
    if not haveMineBonus()then
        return;
    end

    -- 如果已经占领了，则领取矿脉奖励，否则直接清除奖励
    if isAlreadyOccupy() then
        takeMineBonus();
    end
end

-- 离开地牢的回调
function whenLeaveDungeon()
    -- 如果有矿脉奖励
    if haveMineBonus()then
        -- 直接清除
        clearMineBonus();
    end
end

-- 清除矿脉奖励
function clearMineBonus()
    ME.user.dbase:delete("mine_bonus");
    ME.user.dbase:delete("mine_occupy");
    ME.user.dbase:delete("mine_bonus_temp");
end

-- 生成矿脉奖励
function generateMineBonus()
    -- 如果奖励已经生成，直接返回即可（防止玩家刷奖励）
    local mineBonusTemp = ME.user.dbase:query("mine_bonus_temp", {});
    local dungeonId = DungeonM.getDungeonId();
    local layer     = DungeonM.currentLayer();
    if mineBonusTemp["dungeon_id"] == dungeonId and
       mineBonusTemp["layer"] == layer and
       type(mineBonusTemp["bonus_list"]) == 'table' and
       #mineBonusTemp["bonus_list"] > 0 then
        trace("DungeonMineM", "矿脉奖励已经生成，直接返回。");
        --printTable(mineBonusTemp["bonus_list"]);
        return mineBonusTemp["bonus_list"];
    end

    -- 获取奖励持续的层数（每层可领取一个）
    local bonusCount = FormulaM.invoke("CALC_MINE_BONUS_AFFECT_LAYER", ME.user);

    if bonusCount <= 0 then
        return {};
    end

    local bonusList = {};
    local bonus;
    local formula;

    for i = 1, bonusCount do
        -- 获取随机种子
        local randSeed = DungeonM.getRandSeed("mine_bonus");

        -- 根据随机种子抽取一个奖励
        local bonusConfig = fetchElemBySeed(mineList, randSeed);

        -- 计算奖励
        local bonus = FormulaM.invoke(bonusConfig["bonus_formula"], ME.user, bonusConfig["bonus_args"]);

        table.insert(bonusList, bonus);
    end

    ME.user.dbase:set("mine_bonus_temp", {
        ["bonus_list"] = bonusList,
        ["dungeon_id"] = DungeonM.getDungeonId(),
        ["layer"]      = DungeonM.currentLayer(),
    });

    return bonusList;
end

-- 判断当前是否有矿脉奖励可领取
function haveMineBonus()
    local mineBonus = ME.user.dbase:query("mine_bonus");
    if type(mineBonus) ~= 'table' or #mineBonus <= 0 then
        return false;
    end

    return true;
end

-- 领取矿脉奖励
function takeMineBonus()
    local mineBonus = ME.user.dbase:query("mine_bonus");
    if type(mineBonus) ~= 'table' or #mineBonus <= 0 then
        -- 矿脉奖励未生成或已经领取完
        trace("DungeonMineM", "矿脉奖励已领完。");
        return false;
    end

    -- 领取列表中的第一个
    local bonus = mineBonus[1];
    BonusM.doBonus(bonus, "mine_bonus");

    -- 是否是最后一个奖励
    local isLastBonus = iif(#mineBonus == 1, true, false);

    -- 抛出领取矿脉奖励事件
    EventMgr.fire(event.MINE_BONUS_TAKEN, { ["bonus"] = bonus, ["isLastBonus"] = isLastBonus,});

    -- 移除第一个奖励
    table.remove(mineBonus, 1);

    if #mineBonus <= 0 then
        -- 已经没有奖励了，移除矿脉信息
        clearMineBonus();
    else
        ME.user.dbase:set("mine_bonus", mineBonus);
    end

    return true;
end

-- 是否已经占领了矿脉
function isAlreadyOccupy()
    local mineOccupy = ME.user.dbase:query("mine_occupy");
    if type(mineOccupy) ~= 'table' then
        return false;
    end

    local dungeonId = DungeonM.getDungeonId();
    if mineOccupy["dungeon_id"] == dungeonId then
        return true;
    end

    return false;
end

----------------------------
-- 占领矿脉
-- @param pos  矿脉所在的格子
function occupyMine(pos)
    if not DungeonM.checkDungeonAction() then
        -- 经检测，不允许执行地牢行为
        return false;
    end

    local tempBonus = ME.user.dbase:query("mine_bonus_temp", "bonus_list", false);
    if not tempBonus or type(tempBonus) ~= 'table' then
        -- 矿脉奖励未生成，无法占领
        return false;
    end

    local mineOccupy = ME.user.dbase:query("mine_occupy", {});
    local layer     = DungeonM.currentLayer();
    local dungeonId = DungeonM.getDungeonId();
    if mineOccupy["dungeon_id"] == dungeonId and
       mineOccupy["layer"] == layer then
        -- 已经占领过了，不能重复占领
        return false;
    end

    -- 记录占领信息
    mineOccupy["layer"] = layer;
    mineOccupy["dungeon_id"] = dungeonId;
    ME.user.dbase:set("mine_occupy", mineOccupy);

    -- TODO 不是当前层的矿脉，不能占领

    -- 将奖励信息追加到玩家身上
    local mineBonus = ME.user.dbase:query("mine_bonus", {});
    mineBonus = table.append(mineBonus, tempBonus);
    ME.user.dbase:set("mine_bonus", mineBonus);

    -- 将格子设置为无效
    local grid = DungeonM.getGridByPos(pos);
    grid:changeState(GRID_STATE_DISABLE);

    -- 抛出占领矿脉事件
    EventMgr.fire(event.OCCUPY_MINE, { ["pos"] = pos, });

    return true;
end


